﻿using System;
using System.Collections.Generic;
using FireStarterModeller.UI;
using Habanero.Base;
using Habanero.Faces.Base;
using NUnit.Framework;
using Rhino.Mocks;

namespace FireStarterModeller.Test.UI.ErrorProvider
{
    [TestFixture]
    public class TestErrorViewer
    {
        [TestFixtureSetUp]
        public void SetupFixture()
        {
            UITestUtils.SetupFixture();
        }

        [SetUp]
        public virtual void SetupTest()
        {
            UITestUtils.SetupTest();
        }

        protected virtual IControlFactory GetControlFactory()
        {
            return GlobalUIRegistry.ControlFactory;
        }

        [Test]
        public void Test_CreateErrorViewerControl_WithNullControlFactory_ShouldRaiseErrorl()
        {
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            try
            {
                new ErrorViewerControl(null);
                Assert.Fail("expected ArgumentNullException");
            }
                //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("controlFactory", ex.ParamName);
            }
        }

        [Test]
        public void Test_CreateErrorViewerControl_ShouldCreateGridControl()
        {
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            ErrorViewerControl viewerControl = new ErrorViewerControl();
            //---------------Test Result -----------------------
            Assert.AreEqual(1, viewerControl.Controls.Count);
            Assert.IsNotNull(viewerControl);
            Assert.IsNotNull(viewerControl.ErrorViewerGrid);
            Assert.IsInstanceOf(typeof (IDataGridView), viewerControl.ErrorViewerGrid);
        }

        [Test]
        public void Test_CreateErrorViewerControl_WithControlFactory_ShouldCreateGridControl()
        {
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            ErrorViewerControl viewerControl = new ErrorViewerControl(GetControlFactory());
            //---------------Test Result -----------------------
            Assert.IsNotNull(viewerControl);
            IDataGridView errorViewerGrid = viewerControl.ErrorViewerGrid;
            Assert.IsNotNull(errorViewerGrid);
            Assert.IsInstanceOf(typeof (IDataGridView), errorViewerGrid);
            Assert.IsFalse(errorViewerGrid.AllowUserToAddRows);
            Assert.IsFalse(errorViewerGrid.AllowUserToDeleteRows);
            Assert.IsTrue(errorViewerGrid.ReadOnly);
            Assert.AreEqual(DataGridViewSelectionMode.FullRowSelect, errorViewerGrid.SelectionMode);
        }

        [Test]
        public void Test_GridControlSetup_Shouldhave4ColumnsCorrectly()
        {
            //---------------Set up test pack-------------------
            ErrorViewerControl viewerControl = new ErrorViewerControl(GetControlFactory());
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IDataGridView errorViewerGrid = viewerControl.ErrorViewerGrid;
            //---------------Test Result -----------------------
            Assert.AreEqual(4, errorViewerGrid.ColumnCount);
            IDataGridViewColumn column1 = errorViewerGrid.Columns[0];
            Assert.AreEqual("Source", column1.Name);
            Assert.AreEqual("Source", column1.HeaderText);

            IDataGridViewColumn column2 = errorViewerGrid.Columns[1];
            Assert.AreEqual("ErrorMessage", column2.Name);
            Assert.AreEqual("ErrorMessage", column2.HeaderText);

            IDataGridViewColumn column3 = errorViewerGrid.Columns[2];
            Assert.AreEqual("ViewDetails", column3.Name);
            Assert.AreEqual("", column3.HeaderText);

            IDataGridViewColumn column4 = errorViewerGrid.Columns[3];
            Assert.AreEqual("ErrorLevel", column4.Name);
            Assert.AreEqual("Level", column4.HeaderText);

        }

        [Test]
        public void Test_SetErrorList_WhenErrorlistHasNotItems_ShouldSetErrorsInGrid()
        {
            //---------------Set up test pack-------------------
            ErrorViewerControl viewerControl = new ErrorViewerControl(GetControlFactory());
            IList<IBOError> errors = new List<IBOError>();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, errors.Count);
            //---------------Execute Test ----------------------
            viewerControl.ErrorList = errors;
            //---------------Test Result -----------------------
            Assert.AreEqual(0, viewerControl.ErrorViewerGrid.RowCount);
            Assert.AreSame(errors, viewerControl.ErrorList);
        }

        [Test]
        public void Test_SetErrorList_WhenErrorlistHasOneItem_ShouldSetErrorsInGrid()
        {
            //---------------Set up test pack-------------------
            const string expectedMessage = "Some Error Message";
            IBusinessObject bo = TestUtilsDMClass.CreateUnsavedValidDMClass();
            string expectedToString;
            IBOError boError = GetBoError(bo, expectedMessage, out expectedToString);

            ErrorViewerControl viewerControl = new ErrorViewerControl(GetControlFactory());
            IList<IBOError> errors = new List<IBOError> {boError};
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, errors.Count);
            //---------------Execute Test ----------------------
            viewerControl.ErrorList = errors;
            //---------------Test Result -----------------------
            IDataGridView gridView = viewerControl.ErrorViewerGrid;
            Assert.AreEqual(1, gridView.RowCount);
            IDataGridViewRow row1 = gridView.Rows[0];
            Assert.AreEqual(expectedToString, row1.Cells[0].Value);
            Assert.AreEqual(expectedMessage, row1.Cells[1].Value);
            Assert.AreSame(bo, row1.Tag);
        }

        [Test]
        public void Test_SetErrorList_WhenErrorlistHasTwoItem_ShouldSetErrorsInGrid()
        {
            //---------------Set up test pack-------------------
            IBusinessObject bo1;
            string expectedMessage1;
            IBOError boError1 = CreateBoAndBOError(out bo1, out expectedMessage1);

            IBusinessObject bo2;
            string expectedMessage2;
            IBOError boError2 = CreateBoAndBOError(out bo2, out expectedMessage2);
            string expectedToString2 = bo2.ToString();

            ErrorViewerControl viewerControl = new ErrorViewerControl(GetControlFactory());
            IList<IBOError> errors = new List<IBOError> {boError1, boError2};
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, errors.Count);
            //---------------Execute Test ----------------------
            viewerControl.ErrorList = errors;
            //---------------Test Result -----------------------
            IDataGridView gridView = viewerControl.ErrorViewerGrid;
            Assert.AreEqual(2, gridView.RowCount);
            IDataGridViewRow row2 = gridView.Rows[1];
            Assert.AreEqual(expectedToString2, row2.Cells[0].Value);
            Assert.AreEqual(expectedMessage2, row2.Cells[1].Value);
            Assert.AreSame(bo2, row2.Tag);
        }

        private static IBOError CreateBoAndBOError(out IBusinessObject bo, out string expectedMessage)
        {
            expectedMessage = "Some Error Message";
            bo = TestUtilsDMClass.CreateUnsavedValidDMClass();
            string expectedToString;
            return GetBoError(bo, expectedMessage, out expectedToString);
        }

        private static IBOError GetBoError(IBusinessObject bo, string expectedMessage, out string expectedToString)
        {
            expectedToString = bo.ToString();

            IBOError boError = MockRepository.GenerateStub<IBOError>();
            boError.Stub(t => t.BusinessObject).Return(bo);
            boError.Stub(t => t.Message).Return(expectedMessage);
            return boError;
        }
    }
}